package com.expert.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.expert.Mapper.NoticeMapper;
import com.expert.context.BaseContext;
import com.expert.dto.AddNoticeDTO;
import com.expert.enums.NoticeType;
import com.expert.exception.AddException;
import com.expert.pojo.Expert;
import com.expert.pojo.Notice;
import com.expert.pojo.NoticeUser;
import com.expert.pojo.User;
import com.expert.service.*;
import com.expert.vo.NoticeVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Array;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringJoiner;

/**
 * @ClassName: NoticeServiceImpl
 * @Author: cxs
 * @Date: 2024/03/18 13:38
 * @Description:
 **/
@Service
public class NoticeServiceImpl extends ServiceImpl<NoticeMapper, Notice> implements NoticeService {

    @Autowired
    UserService userService;
    @Autowired
    CategoryService categoryService;
    @Autowired
    NoticeUserService noticeUserService;

    @Autowired
    ExpertService expertService;
    /**
     * 添加通知
     *
     * @param addNoticeDTO 添加通知
     */
    @Override
    @Transactional
    public void addNotice(AddNoticeDTO addNoticeDTO) {
        Integer noticeType = addNoticeDTO.getNoticeType();
        if (noticeType.equals( NoticeType.ALL.getCode())){
            addNoticeInfo(addNoticeDTO);
        }else {
            ArrayList<Long> userList = new ArrayList<>(addNoticeDTO.getNoticeUserList());
            addNoticeDTO.getNoticeCategoryList().forEach(category->{
                List<Expert> expertList = this.expertService.lambdaQuery().eq(Expert::getExpertCategory, category).list();
                if (expertList!=null&&expertList.size()>0){
                    List<Long> userIdList = expertList.stream().map(Expert::getExpertUser).toList();
                    userList.addAll(userIdList);
                }
            });
            if (userList.size()==0){
                throw  new AddException("被通知人列表为空");
            }
            Long id=addNoticeInfo(addNoticeDTO);
            userList.forEach(user->{
                NoticeUser noticeUser=new NoticeUser();
                noticeUser.setUserId(user);
                noticeUser.setNoticeId(id);
                this.noticeUserService.save(noticeUser);
            });
        }
    }

    /**
     * 分页查询通知
     *
     * @param page
     * @param pageSize
     * @param noticeTitle
     * @param noticeType
     * @param beginTime
     * @return
     */
    @Override
    public Page<NoticeVo> pageNotice(Integer page, Integer pageSize, String noticeTitle, Integer noticeType, LocalDateTime beginTime,LocalDateTime endTime) {
        Page<Notice> noticePage=new Page<>(page,pageSize);
        page(noticePage,new LambdaQueryWrapper<Notice>()
                .like(StringUtils.isNotEmpty(noticeTitle),Notice::getNoticeTitle,noticeTitle)
                .eq(noticeType!=null,Notice::getNoticeType,noticeType)
                .between(beginTime!=null&endTime!=null,Notice::getCreateTime,beginTime,endTime)
                .orderByDesc(Notice::getCreateTime));
        List<Notice> noticeList = noticePage.getRecords();
        Page<NoticeVo> noticeVoPage=new Page<>();
        BeanUtils.copyProperties(noticePage,noticeVoPage);
        List<NoticeVo> noticeVoList = noticeList.stream().map(notice -> {
            NoticeVo noticeVo = new NoticeVo();
            BeanUtils.copyProperties(notice, noticeVo);
            User user = this.userService.getUserById(notice.getCreateUser());
            noticeVo.setCreateUserName(user.getName());
            List<NoticeUser> noticeUserList = this.noticeUserService.lambdaQuery().eq(NoticeUser::getNoticeId, notice.getId()).list();
            List<Long> userIds = new ArrayList<>();
            userIds = noticeUserList.stream().map(NoticeUser::getUserId).toList();
            if (userIds.size()>0){
                List<User> userList = this.userService.lambdaQuery().in(User::getId, userIds).list();
                StringJoiner stringJoiner = new StringJoiner(",");
                userList.forEach(user1 -> {
                    stringJoiner.add(user1.getName());
                });
                noticeVo.setNoticeUserList(stringJoiner.toString());
            }
            return noticeVo;
        }).toList();
        noticeVoPage.setRecords(noticeVoList);
        return noticeVoPage;
    }

    /**
     * 根据id查询通知
     *
     * @param id
     * @return
     */
    @Override
    public NoticeVo getInfoById(Long id) {
        Notice notice = this.lambdaQuery().eq(Notice::getId, id).one();
        NoticeVo noticeVo=new NoticeVo();
        BeanUtils.copyProperties(notice,noticeVo);
        User user = this.userService.lambdaQuery().eq(User::getId, notice.getCreateUser()).one();
        noticeVo.setCreateUserName(user.getName());
        return noticeVo;
    }

    /**
     * 删除通知消息
     *
     * @param ids
     */
    @Override
    @Transactional
    public void deleteNotice(List<Long> ids) {
        ids.forEach(id->{
            this.noticeUserService.remove(new LambdaQueryWrapper<NoticeUser>().eq(NoticeUser::getNoticeId,id));
        });
        this.removeBatchByIds(ids);
    }

    /**
     * 分页查询用户通知
     *
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public Page<NoticeVo> pageUserNotice(Integer page, Integer pageSize) {
        List<NoticeUser> noticeUserList = this.noticeUserService.lambdaQuery().eq(NoticeUser::getUserId, BaseContext.getCurrentId()).list();
        List<Long> noticeIds = noticeUserList.stream().map(NoticeUser::getNoticeId).toList();
        Page<Notice> noticePage=new Page<>(page,pageSize);

        page(noticePage,new LambdaQueryWrapper<Notice>()
                .eq(Notice::getNoticeType,NoticeType.ALL.getCode())
                .or()
                .in(noticeIds.size()>0,Notice::getId,noticeIds)
                .orderByDesc(Notice::getCreateTime));
        List<Notice> noticeList = noticePage.getRecords();
        System.out.println(noticeList);
        Page<NoticeVo> noticeVoPage=new Page<>();
        BeanUtils.copyProperties(noticePage,noticeVoPage);
        List<NoticeVo> noticeVoList = noticeList.stream().map(notice -> {
            NoticeVo noticeVo = new NoticeVo();
            BeanUtils.copyProperties(notice, noticeVo);
            User user = this.userService.lambdaQuery().eq(User::getId, notice.getCreateUser()).one();
            if (user != null) {
                noticeVo.setCreateUserName(user.getName());
            }
            return noticeVo;
        }).toList();
        noticeVoPage.setRecords(noticeVoList);
        return noticeVoPage;
    }

    /**
     * 修改通知
     *
     * @param notice
     */
    @Override
    public void updateNotice(Notice notice) {
        Notice dbNotice = this.lambdaQuery().eq(Notice::getId, notice.getId()).one();
        if (dbNotice!=null){
            BeanUtils.copyProperties(notice,dbNotice);
            dbNotice.setUpdateUser(BaseContext.getCurrentId());
            dbNotice.setUpdateTime(LocalDateTime.now());
            this.updateById(dbNotice);
        }
    }

    private Long addNoticeInfo(AddNoticeDTO addNoticeDTO) {
        Notice notice=new Notice();
        BeanUtils.copyProperties(addNoticeDTO,notice);
        notice.setCreateTime(LocalDateTime.now());
        notice.setCreateUser(BaseContext.getCurrentId());
        notice.setUpdateTime(LocalDateTime.now());
        notice.setUpdateUser(BaseContext.getCurrentId());
        this.save(notice);
        return notice.getId();
    }
}
